package com.wyw.shiro;

import com.wyw.entity.UserT;
import com.wyw.service.IUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private IUserService userService;

    /**
     * 执行授权逻辑
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行授权逻辑");
        //获取当前登录用户
        Subject subject = SecurityUtils.getSubject();
        UserT user = (UserT) subject.getPrincipal();
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();//SimpleAuthorizationInfo是AuthorizationInfo的实现类
        UserT dbUser = userService.findById(user.getId());
        info.addStringPermission(dbUser.getPerms());
        System.out.println(dbUser.getPerms() + "授权成功");
        return info;
    }

    /**
     * 执行认证逻辑
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("执行认证逻辑");
        //模拟用户名和密码
        //把用户传过来的token转换一下：AuthenticationToken是一个接口，UsernamePasswordToken是其实现类
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        UserT user = userService.findByName(token.getUsername());

        //判断用户名
        if (user == null) {
            return null;//Shiro底层会抛出UnKnowAccountException异常
        }

        //判断密码
        /*
        此处将封装好的user传到了SimpleAuthenticationInfo中
        而SimpleAuthenticationInfo中又会将user传给SimplePrincipalCollection的principal参数
        而SimplePrincipalCollection是PrincipalCollection的实现类
        PrincipalCollection是在授权逻辑doGetAuthorizationInfo中是作为参数传入的，PrincipalCollection是subject包中的接口
        所以授权逻辑中可以通过subject.getPrinciple获取到user

        * */
        return new SimpleAuthenticationInfo(user, user.getPassword(), "");//密码比对不正确抛出IncorrectCredentialsException

    }
}
